﻿using huqiang.Core.HGUI;
using huqiang.Core.UIData;
using huqiang.Data;
using huqiang.UIEvent;
using System;
using UnityEngine;

namespace huqiang.UIComposite
{
    /// <summary>
    /// 滑块条
    /// </summary>
    public unsafe struct SliderInfo
    {
        /// <summary>
        /// 前位置的偏移量
        /// </summary>
        public Vector2 StartOffset;
        /// <summary>
        /// 终点位置的偏移量
        /// </summary>
        public Vector2 EndOffset;
        /// <summary>
        /// 起点位置的握柄缩放
        /// </summary>
        public float MinScale;
        /// <summary>
        /// 终点位置的握柄缩放
        /// </summary>
        public float MaxScale;
        /// <summary>
        /// 方向
        /// </summary>
        public UISlider.Direction direction;
        public static int Size = sizeof(SliderInfo);
        public static int ElementSize = Size / 4;
    }
    public class UISlider : Composite
    {
        public enum Direction
        {
            Horizontal, Vertical
        }
        /// <summary>
        /// 填充的图像主体
        /// </summary>
        public HImage FillImage;
        /// <summary>
        /// 握柄,可空
        /// </summary>
        public HImage Nob;
        /// <summary>
        /// 附加信息
        /// </summary>
        public SliderInfo info;
        float ratio;
        UserEvent callBack;
        Vector2 pos;
        /// <summary>
        /// 设置填充值
        /// </summary>
        /// <param name="value"></param>
        public void SetFillSize(float value)
        {
            if (value < 0)
                value = 0;
            else if (value > 1)
                value = 1;
            if(Nob!=null)
            {
                if (info.direction == Direction.Horizontal)
                {
                    float w = Enity.SizeDelta.x;
                    var size = Nob.SizeDelta;
                    size.x = value * w;
                    Nob.SizeDelta = size;
                    ApplyValue();
                }
                else
                {
                    float w = Enity.SizeDelta.y;
                    var size = Nob.SizeDelta;
                    size.y = value * w;
                    Nob.SizeDelta = size;
                    ApplyValue();
                }
            }
        }
        /// <summary>
        /// 滑块值被改变事件
        /// </summary>
        public Action<UISlider> OnValueChanged;
        /// <summary>
        /// 滑块值改变完毕事件
        /// </summary>
        public Action<UISlider> ValueEndChange;
        /// <summary>
        /// 滑块位置百分比,0-1
        /// </summary>
        public float Percentage { get { return ratio; } set {
                if (value < 0)
                    value = 0;
                else if (value > 1)
                    value = 1;
                ratio = value;
                RatioToPos();
                ApplyValue();
            } }
        /// <summary>
        /// 构造函数
        /// </summary>
        public UISlider()
        {
            info.MinScale = 1;
            info.MaxScale = 1;
        }
        public override void Initial(FakeStruct mod, UIElement script,UIInitializer initializer)
        {
            base.Initial(mod,script,initializer);
            callBack = Enity.RegEvent<UserEvent>();
            callBack.Drag  = Draging;
            callBack.DragEnd = DragEnd;
            callBack.PointerDown = PointDown;
            callBack.AutoColor = false;
            FillImage = script.Find("FillImage") as HImage;
            Nob = script.Find("Nob") as HImage;
            unsafe
            {
                var ex = UIElementLoader.GetCompositeData(mod);
                if (ex != null)
                    info = *(SliderInfo*)ex.ip;
            }
        }
        void Draging(UserEvent back, UserAction action, Vector2 v)
        {
            v.x /= back.GlobalScale.x;
            v.y /= back.GlobalScale.y;
            pos += v;
            ApplyValue();
            if (OnValueChanged != null)
                OnValueChanged(this);
        }
        void DragEnd(UserEvent back, UserAction action, Vector2 v)
        {
            v.x /= back.GlobalScale.x;
            v.y /= back.GlobalScale.y;
            pos += v;
            ApplyValue();
            if (ValueEndChange != null)
                ValueEndChange(this);
        }
        void PointDown(UserEvent back, UserAction action)
        {
            var v = new Vector2(back.GlobalPosition.x,back.GlobalPosition.y);
            pos = action.CanvasPos - v;

            pos.x /= back.GlobalScale.x;
            pos.y /= back.GlobalScale.y;
            pos.x += Enity.m_sizeDelta.x * Enity.Pivot.x;
            pos.y += Enity.m_sizeDelta.y *(1- Enity.Pivot.y);
            ApplyValue();
            if (OnValueChanged != null)
                OnValueChanged(this);
        }
        void RatioToPos()
        {
            var size = Enity.SizeDelta;
            if (info.direction == Direction.Horizontal)
            {
                pos.x = ratio * size.x;
            }
            else
            {
                pos.y = ratio * size.y;
            }
        }
        void ApplyValue()
        {
            var size = Enity.m_sizeDelta;
            if (info.direction == Direction.Horizontal)
            {
                float len = size.x;
                if (pos.x < 0)
                    pos.x = 0;
                else if (pos.x > len)
                    pos.x = len;
                ratio = pos.x / len;
            }
            else
            {
                float len = size.y;
                if (pos.y < 0)
                    pos.y = 0;
                else if (pos.y > len)
                    pos.y = len;
                ratio = pos.y / len;
            }

            if (Nob != null)
            {
                if (info.direction == Direction.Horizontal)
                {
                    float rx = size.x *(1- Enity.Pivot.x);
                    float lx = rx - size.x;
                    float nx = Nob.SizeDelta.x * (0.5f - Nob.Pivot.x);
                    Vector2 start = new Vector2(lx + nx, info.StartOffset.y);
                    Vector2 end = new Vector2(rx - nx, info.EndOffset.y);
                    Vector3 p = (end - start) * ratio + start;
                    Nob.localPosition = p; 
                }
                else
                {
                    float ty = size.y *(1- Enity.Pivot.y);
                    float dy = ty - size.y;
                    float ny = Nob.SizeDelta.y * Nob.Pivot.y;
                    Vector2 start = new Vector2(info.StartOffset.x, dy + ny);
                    Vector2 end = new Vector2(info.EndOffset.x, ty - ny);
                    Vector3 p = (end - start) * ratio + start;
                    Nob.localPosition = p;
                }
                float s = (info.MaxScale - info.MinScale) * ratio + info.MinScale;
                Nob.localScale = new Vector3(s, s, s);
            }
            if(FillImage!=null)
            {
                FillImage.SprType = SpriteType.Filled;
                FillImage.FillAmount = ratio;
            }
        }
    }
}
